﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Dotnet.Utils.Utility.EncryptUtil.Ins
{
    /// <summary>
    /// InsFormatUtil
    /// </summary>
    public class InsFormatUtil
    {
        /// <summary>
        /// 序列化
        /// </summary>
        /// <param name="obj">要序列化的对象</param>
        /// <returns></returns>
        public static byte[] Serialize(object obj)
        {
            IFormatter formatter = new BinaryFormatter();
            MemoryStream stream = new MemoryStream();
            formatter.Serialize(stream, obj);
            return stream.ToArray();

        }
        /// <summary>
        /// 反序列化
        /// </summary>
        /// <param name="bytes">字节数据</param>
        /// <returns></returns>
        public static object Deserialize(byte[] bytes)
        {
            MemoryStream stream = new MemoryStream(bytes);
            IFormatter formatter = new BinaryFormatter();
            return formatter.Deserialize(stream);
        }
        /// <summary>
        /// 将Base64的字符串格式化为标准的Url字符串
        /// </summary>
        /// <param name="sBase64String">Base64的字符串</param>
        /// <returns>标准的Url字符串</returns>
        public static string UrlEncodeBase64String(string sBase64String)
        {
            StringBuilder builder = new StringBuilder(sBase64String);
            builder.Replace("=", "_0").Replace("+", "_1").Replace("/", "_2");
            return builder.ToString();
        }
        /// <summary>
        /// 将标准的Url字符串转化为Base64的字符串
        /// </summary>
        /// <param name="sUrlEncodeString">标准的Url字符串</param>
        /// <returns>Base64的字符串</returns>
        public static string UrlDecodeBase64String(string sUrlEncodeString)
        {
            StringBuilder builder = new StringBuilder(sUrlEncodeString);
            builder.Replace("_0", "=").Replace("_1", "+").Replace("_2", "/");
            return builder.ToString();
        }
        /// <summary>
        /// 将对象序列化成Url上传输的标准字符串
        /// </summary>
        /// <param name="obj">对象</param>
        /// <returns>标准Url字符串</returns>
        public static string SerializeUrlString(object obj)
        {
            return UrlEncodeBase64String(Convert.ToBase64String(Serialize(obj)));
        }
        /// <summary>
        /// 将Url上传输的标准字符串反序列化成对象
        /// </summary>
        /// <param name="sUrlString">标准Url字符串</param>
        /// <returns>对象</returns>
        public static object DeserializeUrlString(string sUrlString)
        {
            return Deserialize(Convert.FromBase64String(UrlDecodeBase64String(sUrlString)));
        }

        public static string ToBase64(object o)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                IFormatter formatter = new BinaryFormatter();
                formatter.Serialize(ms, o);
                byte[] hashsm = ms.GetBuffer();
                return Convert.ToBase64String(hashsm);
            }
        }
        public static byte[] ToByteArray(object o)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                IFormatter formatter = new BinaryFormatter();
                formatter.Serialize(ms, o);
                byte[] hashsm = ms.GetBuffer();
                return hashsm;
            }
        }
        public static object ToObject(byte[] hashsm)
        {
            using (MemoryStream ms = new MemoryStream(hashsm))
            {
                IFormatter formatter = new BinaryFormatter();
                return formatter.Deserialize(ms);
            }
        }
        public static object ToObject(string strBase64)
        {
            byte[] hashsm = Convert.FromBase64String(strBase64);
            using (MemoryStream ms = new MemoryStream(hashsm))
            {
                IFormatter formatter = new BinaryFormatter();
                return formatter.Deserialize(ms);
            }
        }

        public static string GetMD5(string sourceStr)
        {
            byte[] buffer = Encoding.Unicode.GetBytes(sourceStr);
            return GetMD5(buffer);
        }

        public static string GetMD5(byte[] buffer)
        {
            MD5CryptoServiceProvider oMD5Hasher = new MD5CryptoServiceProvider();
            byte[] arrbytHashValue = oMD5Hasher.ComputeHash(buffer);
            string strHashData = BitConverter.ToString(arrbytHashValue);
            return strHashData;


        }

        public static string GetSHA(string sourceStr)
        {
            byte[] data = Encoding.Default.GetBytes(sourceStr);
            return GetSHA(data);
        }
        public static string GetSHA(byte[] buffer)
        {

            SHA1 sha1 = new SHA1CryptoServiceProvider();
            byte[] result = sha1.ComputeHash(buffer);//得到哈希值
            string sha = BitConverter.ToString(result);
            return sha;
        }


        /// <summary>
        /// DES加密字符串
        /// </summary>
        /// <param name="encryptString">待加密的字符串</param>
        /// <param name="encryptKey">加密密钥</param>
        /// <param name="iv">加密向量</param>
        /// <returns>加密成功返回加密后的字符串，失败返回源串</returns>
        public static string GetDes(string encryptString, string encryptKey, string iv)
        {
            try
            {
                if (encryptKey.Length < 8)
                    encryptKey = encryptKey.PadLeft(8, '*');
                if (iv.Length < 8)
                    iv = iv.PadLeft(8, '*');
                byte[] rgbKey = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 8));
                byte[] rgbIV = Encoding.UTF8.GetBytes(iv.Substring(0, 8));
                byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString);
                DESCryptoServiceProvider dCSP = new DESCryptoServiceProvider();
                MemoryStream mStream = new MemoryStream();
                CryptoStream cStream = new CryptoStream(mStream, dCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
                cStream.Write(inputByteArray, 0, inputByteArray.Length);
                cStream.FlushFinalBlock();
                return Convert.ToBase64String(mStream.ToArray());
            }
            catch
            {
                return encryptString;
            }
        }

        /// <summary>
        /// DES解密字符串
        /// </summary>
        /// <param name="decryptString">待解密的字符串</param>
        /// <param name="decryptKey">解密密钥,和加密密钥相同</param>
        /// <param name="iv">加密向量</param>
        /// <returns>解密成功返回解密后的字符串，失败返源串</returns>
        public static string FromDes(string decryptString, string decryptKey, string iv)
        {
            try
            {
                if (decryptKey.Length < 8)
                    decryptKey = decryptKey.PadLeft(8, '*');
                if (iv.Length < 8)
                    iv = iv.PadLeft(8, '*');
                byte[] rgbKey = Encoding.UTF8.GetBytes(decryptKey);
                byte[] rgbIV = Encoding.UTF8.GetBytes(iv.Substring(0, 8));
                byte[] inputByteArray = Convert.FromBase64String(decryptString);
                DESCryptoServiceProvider DCSP = new DESCryptoServiceProvider();
                MemoryStream mStream = new MemoryStream();
                CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
                cStream.Write(inputByteArray, 0, inputByteArray.Length);
                cStream.FlushFinalBlock();
                return Encoding.UTF8.GetString(mStream.ToArray());
            }
            catch
            {
                return decryptString;
            }
        }
        /// <summary>
        /// RSA解密
        /// </summary>
        /// <param name="xmlPrivateKey"></param>
        /// <param name="m_strDecryptString"></param>
        /// <returns></returns>
        public static string RSADecrypt(string xmlPrivateKey, string m_strDecryptString)
        {
            RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
            provider.FromXmlString(xmlPrivateKey);
            int MaxBlockSize = provider.KeySize / 8;    //解密块最大长度限制
            byte[] rgb = Convert.FromBase64String(m_strDecryptString);
            if (rgb.Length > MaxBlockSize)
            {
                using (MemoryStream CrypStream = new MemoryStream(rgb))
                using (MemoryStream PlaiStream = new MemoryStream())
                {
                    byte[] Buffer = new byte[MaxBlockSize];
                    int BlockSize = CrypStream.Read(Buffer, 0, MaxBlockSize);

                    while (BlockSize > 0)
                    {
                        byte[] ToDecrypt = new byte[BlockSize];
                        Array.Copy(Buffer, 0, ToDecrypt, 0, BlockSize);

                        byte[] Plaintext = provider.Decrypt(ToDecrypt, false);
                        PlaiStream.Write(Plaintext, 0, Plaintext.Length);

                        BlockSize = CrypStream.Read(Buffer, 0, MaxBlockSize);
                    }

                    return new UTF8Encoding().GetString(PlaiStream.ToArray());
                }
            }
            else
            {
                byte[] bytes = provider.Decrypt(rgb, false);
                return new UTF8Encoding().GetString(bytes);
            }
        }
        /// <summary>     
        /// RSA加密     
        /// </summary>     
        /// <param name="xmlPublicKey"></param>     
        /// <param name="m_strEncryptString"></param>     
        /// <returns></returns>     
        public static string RSAEncrypt(string xmlPublicKey, string m_strEncryptString)
        {
            RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
            int MaxBlockSize = provider.KeySize / 8 - 11; //加密块最大长度限制
            provider.FromXmlString(xmlPublicKey);
            byte[] bytes = new UTF8Encoding().GetBytes(m_strEncryptString);
            if (m_strEncryptString.Length > MaxBlockSize)
            {
                using (MemoryStream PlaiStream = new MemoryStream(bytes))
                using (MemoryStream CrypStream = new MemoryStream())
                {
                    byte[] Buffer = new byte[MaxBlockSize];
                    int BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);

                    while (BlockSize > 0)
                    {
                        byte[] ToEncrypt = new byte[BlockSize];
                        Array.Copy(Buffer, 0, ToEncrypt, 0, BlockSize);

                        byte[] Cryptograph = provider.Encrypt(ToEncrypt, false);
                        CrypStream.Write(Cryptograph, 0, Cryptograph.Length);

                        BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);
                    }

                    return Convert.ToBase64String(CrypStream.ToArray(), Base64FormattingOptions.None);
                }
            }
            else
            {

                return Convert.ToBase64String(provider.Encrypt(bytes, false));
            }
        }
        /// <summary>
        /// RSA加密
        /// </summary>
        /// <param name="key"></param>
        /// <param name="m_strEncryptString"></param>
        /// <returns></returns>
        public static string RSAEncrypt(AsymmetricAlgorithm key, string m_strEncryptString)
        {
            RSACryptoServiceProvider provider = key as RSACryptoServiceProvider;
            int MaxBlockSize = provider.KeySize / 8 - 11; //加密块最大长度限制
            byte[] bytes = new UTF8Encoding().GetBytes(m_strEncryptString);
            if (m_strEncryptString.Length > MaxBlockSize)
            {
                using (MemoryStream PlaiStream = new MemoryStream(bytes))
                using (MemoryStream CrypStream = new MemoryStream())
                {
                    byte[] Buffer = new byte[MaxBlockSize];
                    int BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);

                    while (BlockSize > 0)
                    {
                        byte[] ToEncrypt = new byte[BlockSize];
                        Array.Copy(Buffer, 0, ToEncrypt, 0, BlockSize);

                        byte[] Cryptograph = provider.Encrypt(ToEncrypt, false);
                        CrypStream.Write(Cryptograph, 0, Cryptograph.Length);

                        BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);
                    }

                    return Convert.ToBase64String(CrypStream.ToArray(), Base64FormattingOptions.None);
                }
            }
            else
            {

                return Convert.ToBase64String(provider.Encrypt(bytes, false));
            }
        }
        /// <summary>
        /// RSA解密
        /// </summary>
        /// <param name="key"></param>
        /// <param name="m_strDecryptString"></param>
        /// <returns></returns>
        public static string RSADecrypt(AsymmetricAlgorithm key, string m_strDecryptString)
        {
            RSACryptoServiceProvider provider = key as RSACryptoServiceProvider;
            int MaxBlockSize = provider.KeySize / 8;    //解密块最大长度限制
            m_strDecryptString = m_strDecryptString.Replace(' ', '+');
            byte[] rgb = Convert.FromBase64String(m_strDecryptString);
            if (rgb.Length > MaxBlockSize)
            {
                using (MemoryStream CrypStream = new MemoryStream(rgb))
                using (MemoryStream PlaiStream = new MemoryStream())
                {
                    byte[] Buffer = new byte[MaxBlockSize];
                    int BlockSize = CrypStream.Read(Buffer, 0, MaxBlockSize);

                    while (BlockSize > 0)
                    {
                        byte[] ToDecrypt = new byte[BlockSize];
                        Array.Copy(Buffer, 0, ToDecrypt, 0, BlockSize);

                        byte[] Plaintext = provider.Decrypt(ToDecrypt, false);
                        PlaiStream.Write(Plaintext, 0, Plaintext.Length);

                        BlockSize = CrypStream.Read(Buffer, 0, MaxBlockSize);
                    }

                    return new UTF8Encoding().GetString(PlaiStream.ToArray());
                }
            }
            else
            {
                byte[] bytes = provider.Decrypt(rgb, false);
                return new UTF8Encoding().GetString(bytes);
            }
        }
    }
}
